package com.lry.basic.netty.protocol.server;

import com.lry.basic.netty.protocol.constant.MsgType;
import com.lry.basic.netty.protocol.constant.ResultType;
import com.lry.basic.netty.protocol.struct.Header;
import com.lry.basic.netty.protocol.struct.NettyMsg;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author:刘仁有
 * @desc:
 * @email:953506233@qq.com
 * @data:2019/9/12
 */
public class LoginAuthRespHandler extends ChannelInboundHandlerAdapter {
    private static final Logger logger = LoggerFactory.getLogger(LoginAuthRespHandler.class);
    private Map<String, Boolean> nodeCheck = new ConcurrentHashMap<String, Boolean>();
    //白名单
    private String[] whitekList = { "127.0.0.1", "192.168.235.100" };

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        NettyMsg nettyMsg = (NettyMsg) msg;
        // 如果是握手请求消息，处理，其它消息透传
        if (nettyMsg.getHeader() != null && nettyMsg.getHeader().getType() == MsgType.LOGIN_REQ.value()) {
            String nodeIndex = ctx.channel().remoteAddress().toString();
            NettyMsg loginResp = null;
            if(nodeCheck.containsKey(nodeIndex)){
                System.out.println("重复登录,拒绝请求!");
                loginResp = buildResponse(ResultType.FAIL);
            }else{
                InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
                String ip = address.getAddress().getHostAddress();
                boolean isOK = false;
                for (String whiteIP : whitekList) {
                    if (whiteIP.equals(ip)) {
                        isOK = true;
                        break;
                    }
                }
                loginResp = isOK ? buildResponse(ResultType.SUCCESS) : buildResponse(ResultType.FAIL);
                if (isOK)
                    nodeCheck.put(nodeIndex, true);
            }
            System.out.println("The login response is :"+loginResp);
            ctx.writeAndFlush(loginResp);
        }else{
            ctx.fireChannelRead(msg);
        }
    }

    /**
     * 服务端接到客户端的握手请求消息后，如果IP校验通过，返回握手成功应答消息给客户端，应用层成功建立链路，否则返回验证失败信息。消息格式如下：
     * 1.消息头的type为4
     * 2.可选附件个数为0
     * 3.消息体为byte类型的结果，0表示认证成功，1表示认证失败
     * @param result
     * @return
     */
    private NettyMsg buildResponse(ResultType result) {
        NettyMsg message = new NettyMsg();
        Header header = new Header();
        header.setType(MsgType.LOGIN_RESP.value());
        message.setHeader(header);
        message.setBody(result.value());
        return message;
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        nodeCheck.remove(ctx.channel().remoteAddress().toString());// 删除缓存
        ctx.close();
        ctx.fireExceptionCaught(cause);
    }
}
